import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {
    public HttpRequest(Socket socket) throws IOException {
        this.socket = socket;
        this.headers = new HashMap<>();
        this.queryParams = new HashMap<>();
        this.pathParams = new HashMap<>();
        parseRequest();
    }

    private void parseRequest() throws IOException {
        InputStream input = socket.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));

        // 获取 请求首部
        String requestLine = reader.readLine();
        if (requestLine == null || requestLine.isEmpty()) {
            throw new IOException("请求 首部 为空！！！");
        }
        if (requestLine.length() > MAX_REQ_LINE) {
            throw new IOException("请求 首部 过长 (" +  requestLine.length() + ") ！！！");
        }
        // 解析 请求首部
        String[] requestParts = requestLine.split(" ");
        if (requestParts.length != 3) {
            throw new IOException("请求行格式非法！！！");
        }
        this.method = requestParts[0];
        String fullPath = requestParts[1];
        this.version = requestParts[2];
        System.out.println("\n成功解析首部字段: " + this.method + " <=> " + fullPath + " <=> " + this.version);
        // 解析 URI
        parsePathAndQuery(fullPath);

        // 获取请求头部
        String headerLine;
        while ((headerLine = reader.readLine()) != null && !headerLine.isEmpty()) {
            if (headerLine.length() > MAX_REQ_HEADER) {
                throw new IOException("请求 头部 过长 (" +  headerLine.length() + ") ！！！");
            }
            int colonIndex = headerLine.indexOf(':');
            if (colonIndex > 0) {
                String key = headerLine.substring(0, colonIndex).trim();
                String value = headerLine.substring(colonIndex + 1).trim();
                headers.put(key.toLowerCase(), value);
            }
        }

        System.out.println("成功解析头部字段：");
        headers.forEach((key, value) -> {
            System.out.println(key + " <=> " + value);
        });
        System.out.println();

        // 解析请求主体
        parseBody(reader);
    }

    // 解析 URI
    private void parsePathAndQuery(String fullPath) throws IOException {
        int queryIndex = fullPath.indexOf('?');
        if (queryIndex >= 0) {
            this.path = fullPath.substring(0, queryIndex);
            String queryString = fullPath.substring(queryIndex + 1);
            parseQueryParams(queryString);
        } else {
            this.path = fullPath;
        }
    }

    // 解析 URI 查询参数
    private void parseQueryParams(String queryString) throws IOException {
        if (queryString == null || queryString.isEmpty()) {
            return;
        }

        String[] paramKVs = queryString.split("&");
        for (String paramKV : paramKVs) {
            String[] keyValue = paramKV.split("=", 2);
            if (keyValue.length == 2) {
                queryParams.put(keyValue[0], keyValue[1]);
            } else {
                throw new IOException("URI 查询参数格式非法 (" + queryString + ") ！！！");
            }
        }
    }

    // 解析主体
    private void parseBody(BufferedReader reader) throws IOException {
        if (!headers.containsKey("content-length")) return;
        String contentLengthStr = headers.get("content-length");
        if (contentLengthStr != null) {
            int contentLength = Integer.parseInt(contentLengthStr);
            if (contentLength > 0) {
                char[] bodyChars = new char[contentLength];
                reader.read(bodyChars, 0, contentLength);
                this.body = new String(bodyChars);
            }
        }
    }

    public String getMethod() { return method; }
    public String getPath() { return path; }
    public String getVersion() { return version; }
    public String getBody() { return body; }
    public Map<String, String> getHeaders() { return headers; }
    public String getHeader(String name) { return headers.get(name.toLowerCase()); }
    public Map<String, String> getQueryParams() { return queryParams; }
    public String getQueryParam(String name) { return queryParams.get(name); }
    public Map<String, String> getPathParams() { return pathParams; }
    public String getPathParameter(String name) { return pathParams.get(name); }

    public void setPathParameter(String name, String value) {
        pathParams.put(name, value);
    }

    @Override
    public String toString() {
        return String.format("HttpRequest{method='%s', path='%s', version='%s'}", method, path, version);
    }

    // 对应连接套接字
    private Socket socket;

    // 请求协议
    private String method;
    private String path;
    private String version;
    private Map<String, String> headers;
    private String body;

    private Map<String, String> pathParams;   // 路径参数
    private Map<String, String> queryParams;  // 请求参数
}
